%% gen_impl.erl
%%   Generating implementation module for a class.
%%
%% Copyright (C) 2008, 2009 Gábor Fehér
%%
%% This file is part of ECT.
%% 
%% ECT is free software: you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%% 
%% ECT is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%% 
%% You should have received a copy of the GNU General Public License
%% along with ECT.  If not, see <http://www.gnu.org/licenses/>.
%%
-module(gen_impl).
-export([create_impl/3]).

-include("common_defs.hrl").

%% Function: create_impl(CompileInfo)
%% Purpose: Creates the abstract syntax tree of the implementation module of a class.
%% Args:
%%   CompileInfo: general info for transforming the compiled class (including its definition)
%%   Options: compile options passed to the Erlang compiler
%% Side-effects:
%%   The binary file of the implementation module is created, by the name outdir/class_implN.beam.
%%      outdir is extracted from Options
%%      class is the name of the class
%%      N is the local version number of the class
create_impl(Forms1, ClassInfo = 
                    #compile_info{cctrans = CCTrans,
                               %local_fields = LocalFields,
                               local_class_data = 
                                    #class_local{
                                        name = ThisClass,
                                        methods = Methods,
                                        fields = LocalFields,
                                        impl_module = ImplModule
                                    } = LocalClassData
                     }, Options) ->

    ImplName = atom_to_list(ImplModule),

    [{attribute, Line, file, {_File, FLine}}|Forms2] = Forms1,

    Forms3 = 
        [{attribute, Line, file, {ImplName++".erl", FLine}}
        ,{attribute, Line, module, ImplModule}
        ,{attribute, Line, export, Methods} 
        ,{attribute, Line, local_class_data, LocalClassData}
        |case CCTrans of
         cctrans ->
           % [{attribute, Line, export, [{new_local, 1}]}];
            [];
         cctrans0 ->
            Fields =
                 lists:map(fun (#class_field{name = Name, value = {atom, _, undefined}}) ->
                                    {record_field, Line, {atom, Line, Name}};
                               (#class_field{name = Name, value = Value}) ->
                                    {record_field, Line, {atom, Line, Name}, Value}
                           end, LocalFields),
                % note: record field '_types' is not included
                % but its okay, there are no type-checks in code generated by cctrans0
                [{attribute, Line, record, {ThisClass, Fields}}]
         end
        ]
        ++
        Forms2,

    Forms4 = CCTrans:parse_transform_class(Forms3, ClassInfo, Options),
    
    modules:compile_forms_to_file(Forms4, Options, ImplModule, "implementation").